/*
 * Copyright 2010-2011 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
package com.staplehurst.aws.sdb;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import com.amazonaws.services.simpledb.model.Attribute;
import com.amazonaws.services.simpledb.model.CreateDomainRequest;
import com.amazonaws.services.simpledb.model.DeleteAttributesRequest;
import com.amazonaws.services.simpledb.model.DeleteDomainRequest;
import com.amazonaws.services.simpledb.model.DomainMetadataRequest;
import com.amazonaws.services.simpledb.model.DomainMetadataResult;
import com.amazonaws.services.simpledb.model.GetAttributesRequest;
import com.amazonaws.services.simpledb.model.GetAttributesResult;
import com.amazonaws.services.simpledb.model.Item;
import com.amazonaws.services.simpledb.model.ListDomainsRequest;
import com.amazonaws.services.simpledb.model.ListDomainsResult;
import com.amazonaws.services.simpledb.model.PutAttributesRequest;
import com.amazonaws.services.simpledb.model.ReplaceableAttribute;
import com.amazonaws.services.simpledb.model.SelectRequest;
import com.staplehurst.aws.client.AmazonClientManager;



/*
 * This class is only slightly modified from the original Amazon SDK. All methods must now be passed
 * a reference to the AmazonClientManager object which decouples this code from any particular
 * Android Activity.
 * 
 * Some very minor adjustments to some of the methods have also be made, plus a few new ones have
 * been added.
 * 
 */


public class SimpleDB {

	private static String nextToken = null;
	private static int prevNumDomains = 0;
	
	public static List<?> getDomainNames(AmazonClientManager clientmanager) {
		return clientmanager.sdb().listDomains().getDomainNames();
	}
	
	public static List<?> getDomainNames(int numDomains, AmazonClientManager clientmanager) {
		prevNumDomains = numDomains;
		return getDomainNames(numDomains, null, clientmanager);
	}
	
	private static List<?> getDomainNames(int numDomains, String nextToken, AmazonClientManager clientmanager) {
		ListDomainsRequest req = new ListDomainsRequest();
		req.setMaxNumberOfDomains(numDomains);
		if(nextToken != null)
			req.setNextToken(nextToken);
		ListDomainsResult result = clientmanager.sdb().listDomains(req);
		List<?> domains = result.getDomainNames();
		SimpleDB.nextToken = result.getNextToken(); 
		return domains;
	}
	
	public static List<?> getMoreDomainNames(AmazonClientManager clientmanager) {
		if(nextToken == null) {
			return new ArrayList<String>();
		} else {
			return getDomainNames(prevNumDomains, nextToken, clientmanager);
		}

	}
	
	public static void createDomain( String domainName, AmazonClientManager clientmanager ) {
		clientmanager.sdb().createDomain( new CreateDomainRequest( domainName ) );
	}
		
	public static void deleteDomain( String domainName, AmazonClientManager clientmanager ) {
		clientmanager.sdb().deleteDomain( new DeleteDomainRequest( domainName ) );
	}

	public static void createItem( String domainName, String itemName, AmazonClientManager clientmanager ) {
		List<ReplaceableAttribute> attributes = new ArrayList<ReplaceableAttribute>(1);
		attributes.add( new ReplaceableAttribute().withName( "Name").withValue( "Value") );
		clientmanager.sdb().putAttributes( new PutAttributesRequest( domainName, itemName, attributes ) );
	}

	public static void createAttributeForItem( String domainName, String itemName, String attributeName, String attributeValue, AmazonClientManager clientmanager ) {
		List<ReplaceableAttribute> attributes = new ArrayList<ReplaceableAttribute>(1);
		attributes.add( new ReplaceableAttribute().withName( attributeName ).withValue( attributeValue ).withReplace( true ) );
		clientmanager.sdb().putAttributes( new PutAttributesRequest( domainName, itemName, attributes ) );
	}

	public static void createRecord( String domainName, String itemName, HashMap<String,String> attribute_data, AmazonClientManager clientmanager ) {		
		List<ReplaceableAttribute> attributes = new ArrayList<ReplaceableAttribute>(attribute_data.size());
		Set<String> keys = attribute_data.keySet();
		String[] keys_array = keys.toArray(new String[keys.size()]);		
		for (int i=0; i < attribute_data.size(); i++) {			
			attributes.add( new ReplaceableAttribute().withName(keys_array[i]).withValue(attribute_data.get(keys_array[i])).withReplace(true));			
		}		
		clientmanager.sdb().putAttributes(new PutAttributesRequest( domainName, itemName, attributes ));
	}
	
	public static String[] getItemNamesForDomain( String domainName, AmazonClientManager clientmanager ) {
		SelectRequest selectRequest = new SelectRequest( "select itemName() from `" + domainName + "`" ).withConsistentRead( true );
		List<?> items = clientmanager.sdb().select( selectRequest ).getItems();			
		String[] itemNames = new String[ items.size() ];
		for ( int i = 0; i < items.size(); i++ ) {
			itemNames[ i ] = ((Item)items.get( i )).getName();
		}		
		return itemNames;
	}

	public static HashMap<String,String> getAttributesForItem( String domainName, String itemName, AmazonClientManager clientmanager ) {
		GetAttributesRequest getRequest = new GetAttributesRequest( domainName, itemName ).withConsistentRead( true );
		GetAttributesResult getResult = clientmanager.sdb().getAttributes( getRequest );			
		HashMap<String,String> attributes = new HashMap<String,String>(30); // Why 30 elements?
		for ( Object attribute : getResult.getAttributes() ) {
			String name = ((Attribute)attribute).getName();
			String value = ((Attribute)attribute).getValue();			
			attributes.put(  name, value );
		}
		return attributes;
	}
	
	public static void updateAttributesForItem( String domainName, String itemName, HashMap<String,String> attributes,
			AmazonClientManager clientmanager) {
		List<ReplaceableAttribute> replaceableAttributes = new ArrayList<ReplaceableAttribute>( attributes.size() ); 		
		for ( String attributeName : attributes.keySet() ) {
			replaceableAttributes.add( new ReplaceableAttribute().withName( attributeName ).withValue( attributes.get( attributeName ) ).withReplace( true ) );
		}
		clientmanager.sdb().putAttributes( new PutAttributesRequest( domainName, itemName, replaceableAttributes ) );
	}

	public static void deleteItem( String domainName, String itemName, AmazonClientManager clientmanager ) {
		clientmanager.sdb().deleteAttributes( new DeleteAttributesRequest( domainName, itemName ) );
	}
	
	public static void deleteItemAttribute( String domainName, String itemName, String attributeName,
			AmazonClientManager clientmanager) { clientmanager.sdb().deleteAttributes(  new DeleteAttributesRequest( domainName, 
					itemName ).withAttributes( new Attribute[] { new Attribute().withName( attributeName ) } ) );
	}
	
	public static int getItemCount (String domainName, AmazonClientManager clientmanager) {		
		int count = 0;
		DomainMetadataRequest domainRequest = new DomainMetadataRequest(domainName);		
		DomainMetadataResult domainResult = clientmanager.sdb().domainMetadata(domainRequest);
		count = domainResult.getItemCount();	
		return count;
		
	}
	
	public static int getNextRecordId (String domainName, AmazonClientManager clientmanager) {	
		int rec_id = 0;
		DomainMetadataRequest domainRequest = new DomainMetadataRequest(domainName);		
		DomainMetadataResult domainResult = clientmanager.sdb().domainMetadata(domainRequest);
		rec_id = domainResult.getItemCount();		
		return rec_id + 1;
	}
	
	public static long getTotalDbSize (String domainName, AmazonClientManager clientmanager) {		
		long db_size = 0;
		DomainMetadataRequest domainRequest = new DomainMetadataRequest(domainName);		
		DomainMetadataResult domainResult = clientmanager.sdb().domainMetadata(domainRequest);
		db_size = domainResult.getItemNamesSizeBytes() + domainResult.getAttributeNamesSizeBytes() + domainResult.getAttributeValuesSizeBytes();
		return db_size;
	}
	
	public static long getTotalDbBillingSize (String domainName, AmazonClientManager clientmanager) {		
		long db_size = getTotalDbSize(domainName, clientmanager);
		long index_size = 0;
		DomainMetadataRequest domainRequest = new DomainMetadataRequest(domainName);		
		DomainMetadataResult domainResult = clientmanager.sdb().domainMetadata(domainRequest);
		index_size = 45 * (domainResult.getItemCount() + domainResult.getAttributeNameCount() + 
				domainResult.getAttributeValueCount());		
		return db_size + index_size;
	}
}
